//
//  RichTextEditorView.swift
//  RichTextEditor
//
//  Created by 李金梁 on 2020/6/23.
//  Copyright © 2020 李金梁. All rights reserved.
//

import UIKit

class RichTextEditorView: UIView {

    var richTools: RichToolsBarView!
    var contentTextView: UITextView!
    
    var isBoldEnabled = false
    var isItalicEnabled = false
    var isUnderlineEnabled = false
    var isDeletelineEnabled = false

    var updatingTextRange: NSRange = NSMakeRange(0, 0)
    
    var placeholderLabel:UILabel!
    
    var htmlString:String? {
        didSet {
            let str = String.init(format: "<head><style>img{max-width:%f !important;height:auto}</style></head>%@", screen_width - 20, htmlString ?? "")
            contentTextView.attributedText = str.attributedString()
        }
    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        contentTextView = UITextView.init(frame: CGRect.init(x: 0, y: 0, width: frame.size.width, height: frame.size.height))
        contentTextView.delegate = self
        contentTextView.isScrollEnabled = true
        self.addSubview(contentTextView)
        placeholderLabel = UILabel.init(frame: CGRect.init(x: 5, y: 10, width: 100, height: 12))
        placeholderLabel.font = UIFont.systemFont(ofSize: 14)
        placeholderLabel.textColor = .darkGray
        placeholderLabel.text = "请输入正文"
        contentTextView.addSubview(placeholderLabel)
        
        reflowTextAttributes()

        
        self.richTools = RichToolsBarView()
        self.richTools.delegate = self
        self.addSubview(self.richTools)
        
    }
    
    // MARK: - Configuration
    
    func reflowTextAttributes() {
        let entireTextColor = UIColor.black
        let entireAttributedText = NSMutableAttributedString(attributedString: contentTextView.attributedText!)
        let entireRange = NSRange(location: 0, length: entireAttributedText.length)
        entireAttributedText.addAttribute(NSAttributedString.Key.foregroundColor, value: entireTextColor, range: entireRange)
        contentTextView.attributedText = entireAttributedText
    }
    
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        // With the background change, we need to re-apply the text attributes.
        reflowTextAttributes()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

}

extension RichTextEditorView {
    
    //添加图片
    func addImage() {
        let attributedText = NSMutableAttributedString(attributedString: contentTextView.attributedText!)
        // Add the image as an attachment.
        if let image = UIImage(named: "text_view_attachment") {
            let attach = NSTextAttachment()
            attach.image = image
            let imageRate = image.size.width / image.size.height
            attach.bounds = CGRect(x: 0, y: 10, width: screen_width - 15, height: (screen_width - 15) / imageRate)
            let imageAttr = NSAttributedString(attachment: attach)
            let mutableAttr = NSMutableAttributedString(attributedString: attributedText)
            mutableAttr.insert(imageAttr, at: self.updatingTextRange.location)
            let rowRate = NSAttributedString(string: "\n")
            mutableAttr.insert(rowRate, at: self.updatingTextRange.location + rowRate.length)
            //再次记住新的光标的位置
            let newSelectedRange = NSMakeRange(self.updatingTextRange.location + rowRate.length, 0)
            contentTextView.attributedText = mutableAttr
            contentTextView.selectedRange = newSelectedRange
        }
    }
    
    //加粗
    func bold() {
        formatBoldSeletedText()
    }
    
    //斜体
    func Italic() {
        formatItalicSeletedText()
    }
    
    //下划线
    func underLine() {
        formatUnderlinedSeletedText()
    }
    
    //删除线
    func deleteLine() {
        formatDeletelinedSeletedText()
    }
    
}

extension RichTextEditorView: RichToolsBarViewDelegate {
    func richText(richTools: RichToolsBarView, toolsType: RichToolsType) {
         switch toolsType {
         case .image:
             self.addImage()
         case .bold:
             self.bold()
         case .italic:
             self.Italic()
         case .underLine:
             self.underLine()
         default:
             break
         }
     }
     
     func richText(richTools: RichToolsBarView, affineTransform form: CGAffineTransform) {
         let height = screen_height - richTools.frame.size.height
         if form.ty < 0 {
             self.contentTextView.frame.size.height = height + form.ty
         } else {
             self.contentTextView.frame.size.height = height
         }
     }
}

extension RichTextEditorView: UITextViewDelegate{
    func textViewDidBeginEditing(_ textView: UITextView) {
        if textView.attributedText.length == 0{
            DispatchQueue.main.async(execute: {
                textView.selectedRange = NSMakeRange(0, 0)
            })
        }
    }
    
    
    func textViewDidChangeSelection(_ textView: UITextView) {
        if textView.attributedText.length == 0 {
            DispatchQueue.main.async(execute: {
                textView.selectedRange = NSMakeRange(0, 0)
                return
            })
        }
        
        updatingTextRange = textView.selectedRange
    }
    
    
    
    func textViewDidChange(_ textView: UITextView) {
        if textView.text.count != 0 {
            placeholderLabel?.isHidden = true
        }else{
            placeholderLabel?.isHidden = false
        }
        
        if textView.text.count > 0 {
            
            let paragraphStyle = NSMutableParagraphStyle.init()
            paragraphStyle.lineSpacing = 4
            let rangeToModify = NSMakeRange((contentTextView.selectedRange.location - 1) > 0 ? contentTextView.selectedRange.location - 1 : 0, 1)
            let attributedString = NSMutableAttributedString(string: "")
            attributedString.append(textView.attributedText)
            attributedString.addAttributes([NSAttributedString.Key.paragraphStyle:paragraphStyle], range: rangeToModify)
            let customFont = UIFont.systemFont(ofSize: 14.0)
            let normalAttributes = [NSAttributedString.Key.font: customFont]
            attributedString.addAttributes(normalAttributes, range: rangeToModify)
            
            _ = self.removeBoldFormat(attributedString, rangeToModify: rangeToModify)
            _ = self.removeItalicFormat(attributedString, rangeToModify: rangeToModify)
            _ = self.removeUnderlineFormat(attributedString, rangeToModify: rangeToModify)
            _ = self.removeDeletelineFormat(attributedString, rangeToModify: rangeToModify)
            
            if isBoldEnabled {
                _ = self.addBoldFormat(attributedString, rangeToModify: rangeToModify)
            }
            
            if isItalicEnabled {
                _ = self.addItalicFormat(attributedString, rangeToModify: rangeToModify)
            }
            
            if isUnderlineEnabled {
                _ = self.addUnderlineFormat(attributedString, rangeToModify: rangeToModify)
            }
            
            if isDeletelineEnabled{
                _ = self.addDeletelineFormat(attributedString, rangeToModify: rangeToModify)
            }
            
            //再次记住新的光标的位置
            let newSelectedRange = NSMakeRange(self.updatingTextRange.location, 0)
            contentTextView.attributedText = attributedString
            contentTextView.selectedRange = newSelectedRange
        }

    }
    
    
    
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        updatingTextRange = range
        return true
    }
    
    
    func formatBoldSeletedText() {
        isBoldEnabled = !isBoldEnabled
        if isBoldEnabled { //字体加粗
            if updatingTextRange.length > 0{
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.addBoldFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                contentTextView.selectedRange = rangeToModify
            }
        } else { //取消加粗
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
               
                _ = self.removeBoldFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                contentTextView.selectedRange = rangeToModify
            }
        }
    }
    
    
    func formatItalicSeletedText() {
        isItalicEnabled = !isItalicEnabled
        if isItalicEnabled { //斜体
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.addItalicFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        } else { //取消斜体
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.removeUnderlineFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        }
    }
    
    func formatUnderlinedSeletedText() {
        isUnderlineEnabled = !isUnderlineEnabled
        if isUnderlineEnabled { //下划线
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.addUnderlineFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        } else {//取消下划线
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.removeUnderlineFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        }
    }
    
    
    func formatDeletelinedSeletedText() {
        isDeletelineEnabled = !isDeletelineEnabled
        if isDeletelineEnabled{//添加删除线
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.addDeletelineFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        }else{ //取消删除线
            if updatingTextRange.length > 0 {
                let rangeToModify = updatingTextRange
                guard rangeToModify.location < contentTextView.attributedText.length else {
                    return
                }
                
                let attributedString = NSMutableAttributedString(string: "")
                attributedString.append(contentTextView.attributedText)
                
                _ = self.removeDeletelineFormat(attributedString, rangeToModify: rangeToModify)
                contentTextView.attributedText = attributedString
                // Set cursor position after modifying attribute
                contentTextView.selectedRange = rangeToModify
            }
        }
        
    }
}


extension UIFont{
    
    func withTraits(_ traits:UIFontDescriptor.SymbolicTraits...) -> UIFont {
        let descriptor = self.fontDescriptor
            .withSymbolicTraits(UIFontDescriptor.SymbolicTraits(traits))
        return UIFont(descriptor: descriptor!, size: 0)
    }
    
    func boldItalic() -> UIFont {
        return withTraits(.traitBold, .traitItalic)
    }
    
    var isBold: Bool {
        return fontDescriptor.symbolicTraits.contains(.traitBold)
    }
    
    var isItalic: Bool {
        return fontDescriptor.symbolicTraits.contains(.traitItalic)
    }
}


// MARK: with text style
extension RichTextEditorView{
    //MARK: bold
    func addBoldFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        let customFont = UIFont.systemFont(ofSize: 14.0)
        let boldAttributes = [NSAttributedString.Key.font: customFont.withTraits(.traitBold)]
        attributedString.addAttributes(boldAttributes, range: rangeToModify)
        return attributedString
    }
    
    func removeBoldFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.enumerateAttributes(in: rangeToModify, options: []) { (attributes, range, _) -> Void in
            for (attribute, object) in attributes {
                if let font = object as? UIFont {
                    if attribute == NSAttributedString.Key.font && font.isBold {
                        attributedString.removeAttribute(attribute, range: range)
                        let customFont = UIFont.systemFont(ofSize: 14.0)
                        let normalAttributes = [NSAttributedString.Key.font: customFont]
                        attributedString.addAttributes(normalAttributes, range: range)
                        break
                    }
                }
            }
        }
        return attributedString
    }
    
    
    //MARK: italic
    func addItalicFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        let customFont = UIFont.italicSystemFont(ofSize: 14.0)
        let italicAttributes = isBoldEnabled ? [NSAttributedString.Key.font: customFont.withTraits(.traitBold, .traitItalic)] : [NSAttributedString.Key.font: customFont.withTraits(.traitItalic)]
        attributedString.addAttributes(italicAttributes, range: rangeToModify)
        return attributedString
    }
    
    func removeItalicFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.enumerateAttributes(in: rangeToModify, options: []) { (attributes, range, _) -> Void in
            for (attribute, object) in attributes {
                if let font = object as? UIFont {
                    if attribute == NSAttributedString.Key.font && font.isItalic {
                        attributedString.removeAttribute(attribute, range: range)
                        let customFont = UIFont.systemFont(ofSize: 14.0)
                        let normalAttributes = [NSAttributedString.Key.font: customFont]
                        attributedString.addAttributes(normalAttributes, range: range)
                        break
                    }
                }
            }
        }
        return attributedString
    }
    
    
    //MARK: underline
    func addUnderlineFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: rangeToModify)
        return attributedString
    }
    
    func removeUnderlineFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.enumerateAttributes(in: rangeToModify, options: []) { (attributes, range, _) -> Void in
            var mutableAttributes = attributes
            mutableAttributes.removeValue(forKey: NSAttributedString.Key.underlineStyle)
            attributedString.setAttributes(mutableAttributes, range: rangeToModify)
        }
        return attributedString
    }
    
    
    //MARK: deleteline
    func addDeletelineFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: rangeToModify)
        return attributedString
    }
    
    
    func removeDeletelineFormat(_ attributedString: NSMutableAttributedString, rangeToModify: NSRange) -> NSAttributedString {
        attributedString.enumerateAttributes(in: rangeToModify, options: []) { (attributes, range, _) -> Void in
            var mutableAttributes = attributes
            mutableAttributes.removeValue(forKey: NSAttributedString.Key.strikethroughStyle)
            attributedString.setAttributes(mutableAttributes, range: rangeToModify)
        }
        return attributedString
    }
    
}





